#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
#include<string.h>
#include<sys/epoll.h>
#include<stdarg.h>

#include"common.h"
#include"client.h"


const int RECV_TIMEOUT=3000;

blockingqueue* msg_queue=NULL;

list_node user_list=NULL;

list_node friend_list=NULL;

pthread_mutex_t print_mutex;

pthread_mutex_t send_mutex;

pthread_rwlock_t usr_list_lock;

const char* BUSSY_INFO="The user is bussy!";

const char* REJECT_INFO="The user reject your application!";

const char* BATTLE_STOP_INFO="Player Stoped this Game!";

const char* EMPTY_INFO="";

void client_init(){
    msg_queue=create_blockingqueue();
    user_list=create_list();
    friend_list=create_list();

    print_mutex=(pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    send_mutex=(pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    usr_list_lock=(pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
}

typedef struct simple_user{
    char name[USER_NAME_LEN+1];
}simple_user;


//assistans
int concurrent_send_msg(int sockfd,Message msg){
    pthread_mutex_lock(&send_mutex);
    int ret=send_msg(sockfd,msg);
    pthread_mutex_unlock(&send_mutex);
    return ret;
}

void concurrent_printf(const char* fmt,...){
    va_list args;
    va_start(args,fmt);
    pthread_mutex_lock(&print_mutex);
    vprintf(fmt,args);
    pthread_mutex_unlock(&print_mutex);
    va_end(args);
}

int is_simple_user_equal(void* o1,void *o2){
    simple_user* u1=(simple_user*)o1;
    simple_user* u2=(simple_user*)o2;
    return strncmp(u1->name,u2->name,USER_NAME_LEN);
}

int find_user(simple_user* user){
    pthread_rwlock_rdlock(&usr_list_lock);
    int index=find_node(user_list,(void*)user,is_simple_user_equal);
    pthread_rwlock_unlock(&usr_list_lock);
    return index;
}

int add_user(simple_user* usr){
    int index=find_user(usr);
    pthread_rwlock_wrlock(&usr_list_lock);
    if(index==-1){
        user_list=add_node(user_list,usr);
    }
    pthread_rwlock_unlock(&usr_list_lock);
    if(index==-1){
        return 1;
    }else{
        return 0;
    }
}

int delete_user(simple_user* usr){
    int index=find_user(usr);
    pthread_rwlock_wrlock(&usr_list_lock);
    if(index!=-1){
        user_list=delete_node(user_list,index);
    }
    pthread_rwlock_unlock(&usr_list_lock);
    if(index!=-1){
        return 1;
    }else{
        return 0;
    }
}

void show_user(void* o){
    simple_user* usr=(simple_user*)o;
    concurrent_printf("%s ",usr->name);
}

void client_finish(){
    pthread_mutex_destroy(&print_mutex);
    destory_bk_queue(msg_queue);
}

MakeFriendRpy create_makefriend_rpy(int is_successful,char* user_name,const char* info){
    MakeFriendRpy mf_rpy;
    memset(&mf_rpy,0,sizeof(MakeFriendMsg));
    mf_rpy.is_success=is_successful;
    memcpy(mf_rpy.user_name,user_name,USER_NAME_LEN);
    memcpy(mf_rpy.info,info,strlen(info));
    return mf_rpy;
}

BattleRequestRpy create_battlerequest_rpy(int is_successful,const char* name,const char* info){
    BattleRequestRpy blr_rpy;
    memset(&blr_rpy,0,sizeof(BattleRequestMsg));
    blr_rpy.is_seccess=is_successful;
    memcpy(blr_rpy.user_name,name,USER_NAME_LEN);
    memcpy(blr_rpy.info,info,strlen(info));
    return blr_rpy;
}

Message create_message(u_int8_t type,void* content,size_t len){
    Message msg;
    memset(&msg,0,sizeof(Message));
    msg.type=type;
    memcpy(msg.content,content,len);
    return msg;
}

void * recv_thread_loop(void *o){
    Client* this=(Client*)o;
    char buf[128];
    memset(buf,0,128);
    int epfd=epoll_create1(0);
    struct epoll_event event;
    event.data.fd=this->recv_sockfd;
    event.events=EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP;
    epoll_ctl(epfd,EPOLL_CTL_ADD,this->recv_sockfd,&event);
    struct epoll_event* events=calloc(MAX_EVENTS_NUM,sizeof(struct epoll_event));
    while(this->state!=OFFLINE){
        int n=epoll_wait(epfd,events,MAX_EVENTS_NUM,RECV_TIMEOUT);
        for(int i=0;i<n;i++){
            if((events[i].events & EPOLLERR) 
                || (events[i].events & EPOLLHUP) 
                || (events[i].events & EPOLLRDHUP)){
                continue;
            }

            if(events[i].events & EPOLLIN){
                if(recv(events[i].data.fd,buf,sizeof(Message),0)==-1){
                    concurrent_printf("recv_thread:recv msg err!\n");
                }else{
                    Message msg;
                    memset(&msg,0,sizeof(Message));
                    memcpy(&msg,buf,sizeof(Message));
                    switch (msg.type){
                        case USER_ONLINE_MSG:{
                            OnlineMsg ol_msg;
                            memcpy(&ol_msg,&msg.content,sizeof(OnlineMsg));
                            simple_user* usr=(simple_user*)calloc(1,sizeof(simple_user));
                            memcpy(usr->name,ol_msg.name,USER_NAME_LEN);
                            if(add_user(usr)){
                                concurrent_printf("%s is online!\n",usr->name);
                            }
                            break;
                        }
                        case USER_OFFLINE_MSG:{
                            OfflineMsg off_msg;
                            memcpy(&off_msg,msg.content,sizeof(OfflineMsg));
                            simple_user usr;
                            memcpy(&usr.name,off_msg.name,USER_NAME_LEN+1);
                            delete_user(&usr);
                            concurrent_printf("%s is offline!\n",off_msg.name);
                            break;
                        }
                        case MAKE_FRIEND_MSG:{
                            MakeFriendMsg mf_msg;
                            memcpy(&mf_msg,msg.content,sizeof(MakeFriendMsg));
                            if(this->state==BUSSY){//如果忙碌则直接拒绝
                                MakeFriendRpy mf_rpy=create_makefriend_rpy(0,mf_msg.user_name,BUSSY_INFO);
                                Message rpy=create_message(MAKE_FRIEND_REPLY,&mf_rpy,sizeof(MakeFriendRpy));
                                if(concurrent_send_msg(this->send_sockfd,rpy)==-1){
                                    concurrent_printf("recv_thread_loop:send makefriend_reply err!\n");
                                }
                            }else{
                                concurrent_printf("New make friend message!\n");
                                Message* msg_ptr=(Message*)calloc(1,sizeof(Message));
                                memcpy(msg_ptr,&msg,sizeof(Message));
                                bq_push(msg_queue,msg_ptr);
                            }
                            break;
                        }
                        case BATTLE_REQUEST_MSG:{
                            BattleRequestMsg blr_msg;
                            memcpy(&blr_msg,msg.content,sizeof(BattleRequestMsg));
                            if(this->state==BUSSY){
                                BattleRequestRpy blr_rpy=create_battlerequest_rpy(0,blr_msg.user_name,BUSSY_INFO);
                                Message rpy=create_message(BATTLE_REQUEST_RPY,&blr_rpy,sizeof(BattleRequestRpy));
                                if(concurrent_send_msg(this->send_sockfd,rpy)==-1){
                                    concurrent_printf("recv_thread_loop:send battle_srequest_reply err!\n");
                                }
                            }else{
                                concurrent_printf("New battle request message!\n");
                                Message* msg_ptr=(Message*)calloc(1,sizeof(Message));
                                memcpy(msg_ptr,&msg,sizeof(Message));
                                bq_push(msg_queue,msg_ptr);
                            }
                            break;   
                        }
                        default:{
                            concurrent_printf("\n recv_thread_loop:err msg type:%d!\n",msg.type);
                            break;
                        }
                    }   
                }
                memset(buf,0,128);
            }
        }
    }
    close(epfd);
    free(events);
    return NULL;
}


Client * create_client(char* addr,u_int16_t acep_port,uint16_t send_port){
    struct sockaddr_in client_sockaddr;
    client_sockaddr.sin_family=PF_INET;
    client_sockaddr.sin_port=htons(acep_port);
    inet_aton(addr,&client_sockaddr.sin_addr);

    Client* this=(Client*)calloc(1,sizeof(Client));
    this->state=INIT;

    int accept_sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(bind(accept_sockfd,(struct sockaddr*)(&client_sockaddr),sizeof(client_sockaddr))==-1){
        concurrent_printf("create_client:accept socket bind err!\n");
        return this;
    }

    if(listen(accept_sockfd,LISTEN_BACK_LOG)==-1){
        concurrent_printf("create_client:accept socket listen err!\n");
        return this;
    }
    this->accept_sockfd=accept_sockfd;

    client_sockaddr.sin_port=htons(send_port);
    int send_sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(bind(send_sockfd,(struct sockaddr*)&client_sockaddr,sizeof(client_sockaddr))==-1){
        concurrent_printf("create_client:send socket bind err!\n");
        return this;
    }

    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family=PF_INET;
    server_sockaddr.sin_port=htons(SERVER_ACEP_PORT);
    inet_aton(SERVER_IP_ADDR,&server_sockaddr.sin_addr);

    if(connect(send_sockfd,(struct sockaddr*)(&server_sockaddr),sizeof(server_sockaddr))==-1){
        concurrent_printf("create_client:send socket connect err!\n");
        return this;
    }
    
    this->send_sockfd=send_sockfd;
    
    struct sockaddr_in connector_sockaddr;
    
    while(1){
        socklen_t s_len=sizeof(connector_sockaddr);
        int recv_sockfd=accept(accept_sockfd,(struct sockaddr*)(&connector_sockaddr),&s_len);
        if( connector_sockaddr.sin_addr.s_addr==server_sockaddr.sin_addr.s_addr){
            this->recv_sockfd=recv_sockfd;
            make_nonblocking(this->recv_sockfd);
            break;
        }
    }

    return this;
}


/*
for process
*/

void show_init_view(){
    concurrent_printf("Please enter your name:(Do not exceed 20 letters)\n");
}

//完成注册功能
int on_init(Client *this){
    show_init_view();
    char name[USER_NAME_LEN+1];
    scanf("%s",name);
    name[USER_NAME_LEN]=0;
    if(strlen(name)>USER_NAME_LEN){
        concurrent_printf("name is too long!\n");
    }else{
        char recv_buf[128];

        RegisterMsg r_msg;
        memcpy(r_msg.name,name,sizeof(name));
        Message msg;
        msg.type=REGISTER_MSG;
        memcpy(msg.content,&r_msg,sizeof(RegisterMsg));
        
        if(concurrent_send_msg(this->send_sockfd,msg)==-1){           
            concurrent_printf("on_init:socket send err!\n");
            return -1;
        }

        concurrent_printf("waitting for reply...\n");

        if(recv(this->send_sockfd,recv_buf,sizeof(Message),0)<=0){
            concurrent_printf("on_init:socket recv err!\n");
            return -1;
        }


        Message reply;
        memcpy(&reply,recv_buf,sizeof(Message));
        if(reply.type!=REGISTER_RPY){
            concurrent_printf("on_init:reply type err!\n");
            return 0;
        }
        RegisterRpy r_rpy;
        memcpy(&r_rpy,reply.content,sizeof(RegisterRpy));
        if(r_rpy.is_successed==1){
            memcpy(this->name,name,USER_NAME_LEN+1);
            concurrent_printf("Register successed!\n");
            this->state=ONLINE;
        }else{
            concurrent_printf("Register failed!%s\n",r_rpy.info);
        }
    }

    return 0;
}

//1
void show_user_list(){
    pthread_rwlock_rdlock(&usr_list_lock);
    concurrent_printf("user list:");
    iter_list(user_list,show_user);
    concurrent_printf("\n");
    pthread_rwlock_unlock(&usr_list_lock);
}

void show_input_err(){
    concurrent_printf("input err! Please input again!\n");
}

void show_mf_success_info(){
    concurrent_printf("The user accept to be your friend!\n");
}

int input_user_name(char* user_name,char* self_name){
    char input[INPUT_LEN];
    memset(input,0,sizeof(input));
    concurrent_printf("Please input user name!\n");
    scanf("%s",input);

    if(strlen(input)>20){
        show_input_err();
        return -1;
    }

    memcpy(user_name,input,USER_NAME_LEN+1);
    if(strncmp(user_name,self_name,USER_NAME_LEN)==0){
        show_input_err();
        concurrent_printf("You can't choose yourself!\n");
        return -1;
    }

    simple_user user;
    memcpy(user.name,input,USER_NAME_LEN+1);
    int index=find_user(&user);
    if(index==-1){
        show_input_err();
        concurrent_printf("The user is not online!\n");
        return -1;
    }
    return 0;
}
//2
void make_friends(Client* this){
    this->state=BUSSY;

    char name[USER_NAME_LEN+1];
    if(input_user_name(name,this->name)==-1){
        this->state=ONLINE;
        return ;
    }

    MakeFriendMsg mf_msg;
    memcpy(mf_msg.user_name,this->name,USER_NAME_LEN+1);
    memcpy(mf_msg.friend_name,name,USER_NAME_LEN+1);

    Message msg;
    msg.type=MAKE_FRIEND_MSG;
    memcpy(msg.content,&mf_msg,sizeof(MakeFriendMsg));

    if(concurrent_send_msg(this->send_sockfd,msg)==-1){
        concurrent_printf("make_friends:send make_friend_msg err!\n");
        this->state=ONLINE;
        return ;
    }
    printf("make_friends:send!\n");

    concurrent_printf("waitting for reply...\n");

    char recv_buf[128];
    if(recv(this->send_sockfd,recv_buf,sizeof(recv_buf),0)==-1){
        concurrent_printf("make_friends:receive make_friend_rpy err!\n");
        this->state=ONLINE;
        return ;
    }

    Message rpy;
    memcpy(&rpy,recv_buf,sizeof(Message));
    if(rpy.type!=MAKE_FRIEND_REPLY){
        concurrent_printf("make_friends:receive message type err!");
        this->state=ONLINE;
        return ;
    }

    MakeFriendRpy mf_rpy;
    memcpy(&mf_rpy,rpy.content,sizeof(MakeFriendRpy));
    if(mf_rpy.is_success){
        simple_user *friend=(simple_user*)calloc(1,sizeof(simple_user));
        memcpy(friend->name,name,USER_NAME_LEN+1);
        friend_list=add_node(friend_list,friend);
        show_mf_success_info();
    }else{
        concurrent_printf("%s\n",mf_rpy.info);
    }

    this->state=ONLINE;
    return ;
}

//3
void show_friend_list(Client* this){
    concurrent_printf("friend list:");
    iter_list(friend_list,show_user);
    concurrent_printf("\n");
}

int input_choice(){
    char input[INPUT_LEN];
    memset(input,0,sizeof(input));
    scanf("%s",input);
    if(strlen(input)>1){
        show_input_err();
        return -1;
    }else{
        char choice=input[0];
        return choice-'0';
    }
}

char* action_str(ACTION action){
    switch(action){
        case STONE:{
            return "STONE";
        }
        case SCISSOR:{
            return "SCISSOR";
        }   
        case CLOTH:{
            return "CLOTH";
        }
        default:{
            return "UNKNOWN";
        }
    }
}

void battle(Client* this){
    concurrent_printf("Guessing game start!\n");
    while(1){
        concurrent_printf("1. Stone; 2.Scissor 3.Cloth\n");
        int choice=-1;
        while(choice!=1 && choice!=2 && choice!=3 && choice!=4){
            choice=input_choice();
        }
        
        ACTION action=(ACTION)choice;
        BattleMsg bl_msg;
        memset(&bl_msg,0,sizeof(BattleMsg));
        bl_msg.action=action;
        memcpy(bl_msg.user_name,this->name,USER_NAME_LEN);

        Message msg;
        msg.type=BATTLE_MSG;
        memcpy(msg.content,&bl_msg,sizeof(BattleMsg));

        if(concurrent_send_msg(this->send_sockfd,msg)==-1){
            concurrent_printf("battle:send battle msg error!\n");
            break;
        }

        concurrent_printf("waitting for reply...\n");

        char recv_buf[128];
        memset(recv_buf,0,sizeof(recv_buf));
        if(recv(this->send_sockfd,recv_buf,sizeof(Message),0)==-1){
            concurrent_printf("battle:recv battle msg error!\n");
            break;
        }

        Message rpy;
        memcpy(&rpy,recv_buf,sizeof(Message));

        int exit_flag=0;
        switch(rpy.type){
            case BATTLE_MSG:{
                BattleMsg btl_rpy;
                memcpy(&btl_rpy,rpy.content,sizeof(BattleMsg));
                printf("Your enemy %s action:%s\n",btl_rpy.user_name,action_str(btl_rpy.action));
                break;
            }
            case BATTLE_STOP_MSG:{
                BattleStopMsg bsp_rpy;
                memcpy(&bsp_rpy,rpy.content,sizeof(BattleStopMsg));
                concurrent_printf("Game Stop! As %s\n",bsp_rpy.stopinfo);
                exit_flag=1;
                break;
            }
            case BATTLE_RESULT_MSG:{
                BattleResultMsg blrt_msg;
                memcpy(&blrt_msg,rpy.content,sizeof(BattleResultMsg));
                concurrent_printf("%s is the winner!\n",blrt_msg.winner);
                exit_flag=1;
                break;
            }
            default:{
                concurrent_printf("battle:wrong message type:%d!\n",msg.type);
                break;
            }
        }
        if(exit_flag){
            break;
        }

    }
    concurrent_printf("Game Over!\n");
}


//4
void challenge_user(Client* this){
    this->state=BUSSY;

    char name[USER_NAME_LEN+1];
    if(input_user_name(name,this->name)==-1){
        this->state=ONLINE;
        return ;
    }

    BattleRequestMsg blr_msg;
    memset(&blr_msg,0,sizeof(BattleMsg));
    memcpy(blr_msg.user_name,this->name,USER_NAME_LEN+1);
    memcpy(blr_msg.enemy_name,name,USER_NAME_LEN+1);

    Message msg;
    msg.type=BATTLE_REQUEST_MSG;
    memcpy(msg.content,&blr_msg,sizeof(BattleRequestMsg));

    if(concurrent_send_msg(this->send_sockfd,msg)==-1){
        concurrent_printf("challenge_user:send battle_request_msg err!\n");
        this->state=ONLINE;
        return ;
    }

    concurrent_printf("waitting for reply...\n");

    char recv_buf[128];
    if(recv(this->send_sockfd,recv_buf,sizeof(Message),0)==-1){
        concurrent_printf("challenge_user:receive battle_request_rpy err!\n");
        this->state=ONLINE;
        return ;
    }

    Message rpy;
    memcpy(&rpy,recv_buf,sizeof(Message));
    if(rpy.type!=BATTLE_REQUEST_RPY){
        concurrent_printf("challenge_user:receive message type err!");
        this->state=ONLINE;
        return ;
    }

    BattleRequestRpy blr_rpy;
    memcpy(&blr_rpy,rpy.content,sizeof(BattleRequestRpy));
    if(blr_rpy.is_seccess){
        concurrent_printf("The user accept your challenge!\n");
        battle(this);
    }else{
        concurrent_printf("Challenge request is rejected!\n"\
                          "%s\n",blr_rpy.info);
    }

    this->state=ONLINE;
    return ;
}

//5
void clear_screen(Client* this){
    concurrent_printf("\033c");
}

void handle_makefriend_msg(Client* this,MakeFriendMsg mf_msg){
    concurrent_printf("%s wants to make a friend with you\n",mf_msg.user_name);
    concurrent_printf("Input :1(accept) 0(reject)\n");
    int choice=-1;
    while(choice!=0 && choice!=1){
        choice=input_choice();
    }

    MakeFriendRpy mf_rpy;
    if(choice){//同意
        mf_rpy=create_makefriend_rpy(choice,mf_msg.user_name,EMPTY_INFO);
    }else{//拒绝
        mf_rpy=create_makefriend_rpy(choice,mf_msg.user_name,REJECT_INFO);
    }
    Message msg=create_message(MAKE_FRIEND_REPLY,&mf_rpy,sizeof(MakeFriendRpy));
    if(concurrent_send_msg(this->send_sockfd,msg)==-1){
        printf("handle_makefriend_msg:send makefriend reply err!\n");
        return ;
    }

    if(choice){
        simple_user *friend=(simple_user*)calloc(1,sizeof(simple_user));
        memcpy(friend->name,mf_msg.user_name,USER_NAME_LEN+1);
        friend_list=add_node(friend_list,friend);
    }
}

void handle_battlerequest_msg(Client* this,BattleRequestMsg blr_msg){
    concurrent_printf("%s wants to play a game with you\n",blr_msg.user_name);
    concurrent_printf("Input :1(accept) 0(reject)\n");
    int choice=-1;
    while(choice!=0 && choice!=1){
        choice=input_choice();
    }

    BattleRequestRpy blr_rpy;
    if(choice){
        blr_rpy=create_battlerequest_rpy(choice,blr_msg.user_name,EMPTY_INFO);
    }else{
        blr_rpy=create_battlerequest_rpy(choice,blr_msg.user_name,REJECT_INFO);
    }
    Message msg=create_message(BATTLE_REQUEST_RPY,&blr_rpy,sizeof(BattleRequestRpy));
    if(concurrent_send_msg(this->send_sockfd,msg)==-1){
        printf("handle_battlerequest_msg:send battle request reply err!\n");
    }else{
        if(choice){
            battle(this);
        }   
    }
}

//6
void handle_messages(Client* this){
    this->state=BUSSY;
    void *o=NULL;
    printf("handle messages!\n");
    while((o=bq_ub_poll(msg_queue,0))!=NULL){
        Message* msg=(Message*)o;
        switch(msg->type){
            case MAKE_FRIEND_MSG:{
                MakeFriendMsg mf_msg;
                memset(&mf_msg,0,sizeof(MakeFriendMsg));
                memcpy(&mf_msg,msg->content,sizeof(MakeFriendMsg));
                handle_makefriend_msg(this,mf_msg);
                break;
            }
            case BATTLE_REQUEST_MSG:{
                BattleRequestMsg blr_msg;
                memset(&blr_msg,0,sizeof(BattleRequestMsg));
                memcpy(&blr_msg,msg->content,sizeof(BattleRequestMsg));
                handle_battlerequest_msg(this,blr_msg);
                break;
            }
            default:{
                concurrent_printf("handle_messages:err message type:%d!\n",msg->type);
                break;
            }
        }
        free(msg);
    }
    this->state=ONLINE;
}

//7
void client_exit(Client* this){
    this->state=OFFLINE;
}

void show_online_view(Client* this){
    concurrent_printf("\nWelcome to guessing game!%s\n"\
    "Please enter the given number to choose what to do\n"\
    "1.show user list  2.make frineds  3.friends list\n"\
    "4.play a game     5.clear screen  6.handle messages \n"\
    "7.exit\n",this->name);
}

int on_online(Client *this){
    show_online_view(this);

    char input[INPUT_LEN];
    memset(input,0,sizeof(input));
    scanf("%s",input);

    if(strlen(input)>1){
        show_init_view();
        return 0;
    }
    
    char choice=input[0];
    switch (choice){
        case '1':{
            show_user_list();
            break;
        }
        case '2':{
            make_friends(this);
            break;
        }
        case '3':{
            show_friend_list(this);
            break;
        }
        case '4':{
            challenge_user(this);
            break;
        }
        case '5':{
            clear_screen(this);
            break;
        }
        case '6':{
            handle_messages(this);
            break;
        }
        case '7':{
            client_exit(this);
            break;
        }
        default:{
            show_input_err();
            break; 
        }
    }
    return 0;
}

int on_offline(Client* this){
    return -1;
}

Client* process_client(Client* this){
    pthread_t recv_thread;
    pthread_create(&recv_thread,NULL,recv_thread_loop,(void*)this);

    while(1){//正常结束return 0，结束程序 return -1
        int flag=0;
        switch (this->state){
        case INIT:
            flag=on_init(this);
            break;
        case ONLINE:
            flag=on_online(this);
            break;
        case OFFLINE:
            flag=on_offline(this);
            break;
        default:
            concurrent_printf("process_client:wrong state-default!\n");
            flag=-1;
            break;
        }

        if(flag==-1)
            break;
    }

    this->state=OFFLINE;

    pthread_join(recv_thread,NULL);
    return this;
}



Client * close_client(Client* this){
    if(this==NULL)return NULL;
    close(this->send_sockfd);
    close(this->recv_sockfd);
    return this;
}

Client * destory_client(Client* this){
    if(this==NULL)return NULL;
    free(this);
    return NULL;
}


int main(int argc,char **arg){
    if(argc!=2){
        concurrent_printf("input err!\n");
        return -1;
    }
    client_init();
    Client* client=create_client(arg[1],CLIENT_ACEP_PORT,CLIENT_SEND_PORT);
    client=process_client(client);
    client=close_client(client);
    client=destory_client(client);
    return 0;
}